package com.bs.utils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
/**
 * 解决get和post请求 全部乱码的过滤器
 */
@WebFilter(urlPatterns = "/*")
public class AEncodingFilter implements Filter {

//	初始化方法
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
//	每次请求的过滤方法
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		// 转型为与协议相关对象
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		
		HttpServletResponse httpServletResponse=(HttpServletResponse) response;
		
		httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
		/* 允许跨域的请求方法GET, POST, HEAD 等 */
		httpServletResponse.setHeader("Access-Control-Allow-Methods", "*");
		// TODO Auto-generated method stub
		/* 重新预检验跨域的缓存时间 (s) */
		httpServletResponse.setHeader("Access-Control-Max-Age", "4200"); 
		/* 允许跨域的请求头 */
		httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
		/* 是否携带cookie */
		httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
		
		// 处理response的字符编码
		httpServletResponse.setContentType("text/html;charset=UTF-8");
		// 对request包装增强
		chain.doFilter(new EncodingRequest(httpServletRequest), response);
	}
//	销毁方法
	@Override
	public void destroy() {
	}

}

//自定义request对象，HttpServletRequest的包装类
class EncodingRequest extends HttpServletRequestWrapper {

	private HttpServletRequest request;
	// 是否编码的标记
	private boolean hasEncode;
	private Map<String, String[]> parameterMap;
	private String method;

	// 定义一个可以传入HttpServletRequest对象的构造函数，以便对其进行装饰
	public EncodingRequest(HttpServletRequest request) {
		super(request);// super必须写
		this.request = request;
	}

	// 对需要增强方法 进行覆盖
	@Override
	public Map getParameterMap() {
		if (!hasEncode) {
			method = request.getMethod();
			if (method.equalsIgnoreCase("post")) {
				// post请求
				try {
					// 处理post乱码
					request.setCharacterEncoding("utf-8");
					parameterMap = request.getParameterMap();
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			} else if (method.equalsIgnoreCase("get")) {
				// get请求
				parameterMap = request.getParameterMap();
				String serverInfo = request.getServletContext().getServerInfo();
				int version = Integer.parseInt(serverInfo.split("/")[1].split("\\.")[0]);
				if (serverInfo.startsWith("Apache Tomcat")&&version<8) {
					for (String parameterName : parameterMap.keySet()) {
						String[] values = parameterMap.get(parameterName);
						if (values != null) {
							for (int i = 0; i < values.length; i++) {
								try {
									// 处理get乱码
									values[i] = new String(values[i].getBytes("ISO-8859-1"), "UTF-8");
								} catch (UnsupportedEncodingException e) {
									e.printStackTrace();
								}
							}
						}
					}
				}
			}
			hasEncode = true;
			for (String parameterName : parameterMap.keySet()) {
				String[] values = parameterMap.get(parameterName);
				if (values != null) {
					for (int i = 0; i < values.length; i++) {
						if (values[i].equals("")) {
							values[i]=null;
						}
					}
				}
			}
		}
		return parameterMap;
	}

	// 取一个值
	@Override
	public String getParameter(String name) {
		Map<String, String[]> parameterMap = getParameterMap();
		String[] values = parameterMap.get(name);
		if (values == null) {
			return null;
		}
		return values[0]; // 取回参数的第一个值
	}

	// 取所有值
	@Override
	public String[] getParameterValues(String name) {
		Map<String, String[]> parameterMap = getParameterMap();
		String[] values = parameterMap.get(name);
		return values;
	}
}
